home *** CD-ROM | disk | FTP | other *** search
- ; Program Name: PRG_4AP.S
-
- ; Assembly Instructions:
-
- ; Assemble in PC-relative mode and save with a TOS suffix.
-
- ; Program Function:
-
- ; This program simply establishes itself in memory as a Load and Stay
- ; Resident (LSR) program and prints its location to the video screen. The
- ; addresses printed are the program start address (not the basepage address)
- ; and the program end address.
-
- ; Program Purpose:
-
- ; To illustrate the role of GEMDOS function $31 in establishing a
- ; program as LSR.
-
- ; Execution Instructions:
-
- ; Execute the program from the desktop. When the addresses appear on
- ; the screen, write them down. Terminate execution by pressing the Return
- ; key. In the AssemPro debugger, go to the first address using the
- ; "from address" function. On the first line in the output field, you
- ; should see the second address (program_end) being loaded into register A3.
-
- ; Once this program has been executed, it will remain in ram memory until
- ; the computer is rebooted.
-
- ; WARNING: If this program or any other LSR program is executed from within
- ; the AssemPro debugger, upon exit from AssemPro, the operating
- ; system will not be able to clear the program from memory.
-
- ; Because the program will be residing in an area of memory that
- ; was controlled by AssemPro, the environment will be corrupted.
- ; You can confirm this by trying to reexecute AssemPro after you
- ; exit. You will receive a Bus error message.
-
- ; Furthermore, you will not be able to assemble a program until
- ; you reset the system.
-
- ; There is only one thing you can do if you execute a LSR program
- ; from within AssemPro; you must reset the system by turning it
- ; completely off, then back on. You can try a warm reset, but
- ; all bets are off if you do that.
-
- program_start: ; Calculate program size and retain result.
- lea program_end, a3 ; Fetch address of last memory location occupied
- movea.l a3, a4 ; by the program. Copy into scratch register.
- suba.l 4(a7), a3 ; Subtract basepage address from program end
- ; address. After this, the basepage address
- ; is no longer needed in this program.
- fetch_stack_address:
- lea stack, a7
-
- print_memory_locations:
- lea load_message, a0
- bsr.s print_string
- lea program_start, a0
- move.l a0, d1 ; Transfer to D1 for binary to ASCII
- ; hexadecimal conversion.
-
- ; Note: Above, must load address into an address register first, then move
- ; to the data register for binary to hexadecimal conversion, in order to
- ; permit PC-relative assembly.
-
- bsr.s bin_to_hex ; bin_to_hex expects binary number in D1.
- lea hexadecimal, a0 ; Print the hexadecimal string.
- bsr.s print_string
- lea separator, a0 ; Print a separator between addresses.
- bsr.s print_string
- move.l a4, d1 ; Program end address is in scratch register.
- bsr.s bin_to_hex
- lea hexadecimal, a0
- bsr.s print_string
- bsr.s print_newline
-
- wait_for_keypress: ; Give time to write down memory addresses.
- move.w #8, -(sp) ; Function = c_necin = GEMDOS $8.
- trap #1 ; GEMDOS call.
- addq.l #2, sp
-
- ; Note: GEMDOS function $31 doesn't need the basepage address.
-
- relinquish_processor_control: ; Maintain memory residency.
- move.w #0, -(sp) ; See page 121 of Internals book.
- move.l a3, -(sp) ; Program size.
- move.w #$31, -(sp) ; Function = ptermres = GEMDOS $31.
- trap #1
-
- ;
- ; SUBROUTINES
- ;
-
- ; The binary to ASCII hexadecimal conversion routine expects a number to be
- ; passed as a longword in register D1. Beginning with the most significant
- ; nibble (a nibble = four bits), each nibble is converted to its ASCII
- ; hexadecimal equivalent and stored in "hexadecimal", a null terminated
- ; buffer. Maximum size of the binary number is 32 bits = 8 nibbles.
-
- ; The algorithm discards leading zeroes.
-
- ; The conversion from binary nibble to hex digit is accomplished by
- ; extracting the character in the hex table that is located at the position
- ; defined by the decimal value of the nibble. For example, if the nibble
- ; is "1111", the decimal value is 15; the 15th element of the hex table is
- ; the letter F. The location in the table is specified by an offset from
- ; the address of the first character of the table, which is stored in A1.
- ; The value of the offset is stored in register D0. The addressing mode
- ; used to locate the appropriate table entry is "address register indirect
- ; with offset".
-
- bin_to_hex: ; Expects binary number in D1.
- lea hexadecimal, a0 ; A0 is pointer to array "hexadecimal".
- tst.l d1 ; Test for contents = 0.
- beq.s zero_passed ; Branch if number is 0.
- lea hex_table, a1 ; A1 is pointer to array "hex_table".
- lea hex_table, a1 ; A1 is pointer to array "hex_table".
- moveq #7, d2 ; D2 is the loop counter for 8 nibbles.
-
- discard_leading_zeroes:
- rol.l #4, d1 ; Rotate most significant nibble to the
- ; least significant nibble position.
- move.b d1, d0 ; Copy least significant byte of D1 to D0.
- andi.b #$F, d0 ; Mask out most significant nibble of D0.
- bne.s store_digit ; Branch and store if not leading zero.
- dbra d2, discard_leading_zeroes
- continue:
- rol.l #4, d1 ; Rotate most significant nibble.
- move.b d1, d0 ; Copy least significant byte of D1 to D0.
- andi.b #$F, d0 ; Mask out most significant nibble of D0.
- store_digit:
- move.b 0(a1,d0.w), (a0)+ ; Store ASCII hexadecimal digit in buffer.
- dbra d2, continue ; Continue looping until D2 = -1.
- move.b #0, (a0) ; Terminate hexadecimal string with a null.
- rts
- zero_passed:
- move.b #$30, (a0)+ ; Store an ASCII zero in "hexadecimal".
- move.b #0, (a0) ; Terminate ASCII hexadecimal string with null.
- lea hexadecimal, a0
- rts
-
- print_string: ; Expects address of string to be in A0.
- pea (a0) ; Push address of string onto stack.
- move.w #9, -(sp) ; Function = c_conws = GEMDOS $9.
- trap #1 ; GEMDOS call
- addq.l #6, sp ; Reset stack pointer to top of stack.
- rts
-
- print_newline: ; Prints a carriage return and linefeed.
- pea newline ; Push address of string onto stack.
- move.w #9, -(sp) ; Function = c_conws = GEMDOS $9.
- trap #1 ; GEMDOS call
- addq.l #6, sp
- rts
-
- data
- hex_table: dc.b '0123456789ABCDEF'
- newline: dc.b $D,$A,0
- load_message: dc.b 'Installing PRG_4AP between hex addresses: ',0
- separator: dc.b ' - ',0
- align
- bss
- hexadecimal: ds.l 3 ; Output buffer. Must be NULL terminated.
- ds.l 16
- stack: ds.l 1
- program_end: ds.l 0
- end